﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.Windows.WebCam.VideoCapture
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using UnityEngine.Bindings;
using UnityEngine.Scripting;
using UnityEngine.Scripting.APIUpdating;

#nullable disable
namespace UnityEngine.Windows.WebCam
{
  /// <summary>
  ///   <para>Records a video from the web camera directly to disk.</para>
  /// </summary>
  [NativeHeader("PlatformDependent/Win/Webcam/VideoCaptureBindings.h")]
  [StaticAccessor("VideoCaptureBindings", StaticAccessorType.DoubleColon)]
  [MovedFrom("UnityEngine.XR.WSA.WebCam")]
  [StructLayout(LayoutKind.Sequential)]
  public class VideoCapture : IDisposable
  {
    internal IntPtr m_NativePtr;
    private static Resolution[] s_SupportedResolutions;
    private static readonly long HR_SUCCESS;

    private static VideoCapture.VideoCaptureResult MakeCaptureResult(
      VideoCapture.CaptureResultType resultType,
      long hResult)
    {
      return new VideoCapture.VideoCaptureResult()
      {
        resultType = resultType,
        hResult = hResult
      };
    }

    private static VideoCapture.VideoCaptureResult MakeCaptureResult(long hResult)
    {
      return new VideoCapture.VideoCaptureResult()
      {
        resultType = hResult != VideoCapture.HR_SUCCESS ? VideoCapture.CaptureResultType.UnknownError : VideoCapture.CaptureResultType.Success,
        hResult = hResult
      };
    }

    /// <summary>
    ///   <para>A list of all the supported device resolutions for recording videos.</para>
    /// </summary>
    public static IEnumerable<Resolution> SupportedResolutions
    {
      get
      {
        if (VideoCapture.s_SupportedResolutions == null)
          VideoCapture.s_SupportedResolutions = VideoCapture.GetSupportedResolutions_Internal();
        return (IEnumerable<Resolution>) VideoCapture.s_SupportedResolutions;
      }
    }

    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [NativeName("GetSupportedResolutions")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern Resolution[] GetSupportedResolutions_Internal();

    /// <summary>
    ///   <para>Returns the supported frame rates at which a video can be recorded given a resolution.</para>
    /// </summary>
    /// <param name="resolution">A recording resolution.</param>
    /// <returns>
    ///   <para>The frame rates at which the video can be recorded.</para>
    /// </returns>
    public static IEnumerable<float> GetSupportedFrameRatesForResolution(Resolution resolution)
    {
      return (IEnumerable<float>) VideoCapture.GetSupportedFrameRatesForResolution_Internal(resolution.width, resolution.height);
    }

    [NativeName("GetSupportedFrameRatesForResolution")]
    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern float[] GetSupportedFrameRatesForResolution_Internal(
      int resolutionWidth,
      int resolutionHeight);

    /// <summary>
    ///   <para>Indicates whether or not the VideoCapture instance is currently recording video.</para>
    /// </summary>
    public extern bool IsRecording { [NativeMethod("VideoCaptureBindings::IsRecording", HasExplicitThis = true), NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE"), MethodImpl(MethodImplOptions.InternalCall)] get; }

    public static void CreateAsync(
      bool showHolograms,
      VideoCapture.OnVideoCaptureResourceCreatedCallback onCreatedCallback)
    {
      if (onCreatedCallback == null)
        throw new ArgumentNullException(nameof (onCreatedCallback));
      VideoCapture.Instantiate_Internal(showHolograms, onCreatedCallback);
    }

    public static void CreateAsync(
      VideoCapture.OnVideoCaptureResourceCreatedCallback onCreatedCallback)
    {
      if (onCreatedCallback == null)
        throw new ArgumentNullException(nameof (onCreatedCallback));
      VideoCapture.Instantiate_Internal(false, onCreatedCallback);
    }

    [NativeName("Instantiate")]
    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void Instantiate_Internal(
      bool showHolograms,
      VideoCapture.OnVideoCaptureResourceCreatedCallback onCreatedCallback);

    [RequiredByNativeCode]
    private static void InvokeOnCreatedVideoCaptureResourceDelegate(
      VideoCapture.OnVideoCaptureResourceCreatedCallback callback,
      IntPtr nativePtr)
    {
      if (nativePtr == IntPtr.Zero)
        callback((VideoCapture) null);
      else
        callback(new VideoCapture(nativePtr));
    }

    private VideoCapture(IntPtr nativeCaptureObject) => this.m_NativePtr = nativeCaptureObject;

    public void StartVideoModeAsync(
      CameraParameters setupParams,
      VideoCapture.AudioState audioState,
      VideoCapture.OnVideoModeStartedCallback onVideoModeStartedCallback)
    {
      if (onVideoModeStartedCallback == null)
        throw new ArgumentNullException(nameof (onVideoModeStartedCallback));
      if (setupParams.cameraResolutionWidth == 0 || setupParams.cameraResolutionHeight == 0)
        throw new ArgumentOutOfRangeException(nameof (setupParams), "The camera resolution must be set to a supported resolution.");
      if ((double) setupParams.frameRate == 0.0)
        throw new ArgumentOutOfRangeException(nameof (setupParams), "The camera frame rate must be set to a supported recording frame rate.");
      this.StartVideoMode_Internal(setupParams, audioState, onVideoModeStartedCallback);
    }

    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [NativeMethod("VideoCaptureBindings::StartVideoMode", HasExplicitThis = true)]
    private void StartVideoMode_Internal(
      CameraParameters cameraParameters,
      VideoCapture.AudioState audioState,
      VideoCapture.OnVideoModeStartedCallback onVideoModeStartedCallback)
    {
      this.StartVideoMode_Internal_Injected(ref cameraParameters, audioState, onVideoModeStartedCallback);
    }

    [RequiredByNativeCode]
    private static void InvokeOnVideoModeStartedDelegate(
      VideoCapture.OnVideoModeStartedCallback callback,
      long hResult)
    {
      callback(VideoCapture.MakeCaptureResult(hResult));
    }

    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [NativeMethod("VideoCaptureBindings::StopVideoMode", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void StopVideoModeAsync(
      [NotNull("ArgumentNullException")] VideoCapture.OnVideoModeStoppedCallback onVideoModeStoppedCallback);

    [RequiredByNativeCode]
    private static void InvokeOnVideoModeStoppedDelegate(
      VideoCapture.OnVideoModeStoppedCallback callback,
      long hResult)
    {
      callback(VideoCapture.MakeCaptureResult(hResult));
    }

    public void StartRecordingAsync(
      string filename,
      VideoCapture.OnStartedRecordingVideoCallback onStartedRecordingVideoCallback)
    {
      if (onStartedRecordingVideoCallback == null)
        throw new ArgumentNullException(nameof (onStartedRecordingVideoCallback));
      string path = !string.IsNullOrEmpty(filename) ? Path.GetDirectoryName(filename) : throw new ArgumentNullException(nameof (filename));
      if (!string.IsNullOrEmpty(path) && !System.IO.Directory.Exists(path))
        throw new ArgumentException("The specified directory does not exist.", nameof (filename));
      FileInfo fileInfo = new FileInfo(filename);
      if (fileInfo.Exists && fileInfo.IsReadOnly)
        throw new ArgumentException("Cannot write to the file because it is read-only.", nameof (filename));
      this.StartRecordingVideoToDisk_Internal(fileInfo.FullName, onStartedRecordingVideoCallback);
    }

    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [NativeMethod("VideoCaptureBindings::StartRecordingVideoToDisk", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void StartRecordingVideoToDisk_Internal(
      string filename,
      VideoCapture.OnStartedRecordingVideoCallback onStartedRecordingVideoCallback);

    [RequiredByNativeCode]
    private static void InvokeOnStartedRecordingVideoToDiskDelegate(
      VideoCapture.OnStartedRecordingVideoCallback callback,
      long hResult)
    {
      callback(VideoCapture.MakeCaptureResult(hResult));
    }

    [NativeMethod("VideoCaptureBindings::StopRecordingVideoToDisk", HasExplicitThis = true)]
    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void StopRecordingAsync(
      [NotNull("ArgumentNullException")] VideoCapture.OnStoppedRecordingVideoCallback onStoppedRecordingVideoCallback);

    [RequiredByNativeCode]
    private static void InvokeOnStoppedRecordingVideoToDiskDelegate(
      VideoCapture.OnStoppedRecordingVideoCallback callback,
      long hResult)
    {
      callback(VideoCapture.MakeCaptureResult(hResult));
    }

    /// <summary>
    ///   <para>Provides a COM pointer to the native IVideoDeviceController.</para>
    /// </summary>
    /// <returns>
    ///   <para>A native COM pointer to the IVideoDeviceController.</para>
    /// </returns>
    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [NativeMethod("VideoCaptureBindings::GetUnsafePointerToVideoDeviceController", HasExplicitThis = true)]
    [ThreadAndSerializationSafe]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern IntPtr GetUnsafePointerToVideoDeviceController();

    /// <summary>
    ///   <para>You must call Dispose to shutdown the VideoCapture instance and release the native WinRT objects.</para>
    /// </summary>
    public void Dispose()
    {
      if (this.m_NativePtr != IntPtr.Zero)
      {
        this.Dispose_Internal();
        this.m_NativePtr = IntPtr.Zero;
      }
      GC.SuppressFinalize((object) this);
    }

    [NativeMethod("VideoCaptureBindings::Dispose", HasExplicitThis = true)]
    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void Dispose_Internal();

    ~VideoCapture()
    {
      if (!(this.m_NativePtr != IntPtr.Zero))
        return;
      this.DisposeThreaded_Internal();
      this.m_NativePtr = IntPtr.Zero;
    }

    [NativeConditional("(PLATFORM_WIN || PLATFORM_WINRT) && !PLATFORM_XBOXONE")]
    [ThreadAndSerializationSafe]
    [NativeMethod("VideoCaptureBindings::DisposeThreaded", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void DisposeThreaded_Internal();

    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void StartVideoMode_Internal_Injected(
      ref CameraParameters cameraParameters,
      VideoCapture.AudioState audioState,
      VideoCapture.OnVideoModeStartedCallback onVideoModeStartedCallback);

    /// <summary>
    ///   <para>Contains the result of the capture request.</para>
    /// </summary>
    public enum CaptureResultType
    {
      /// <summary>
      ///   <para>Specifies that the desired operation was successful.</para>
      /// </summary>
      Success,
      /// <summary>
      ///   <para>Specifies that an unknown error occurred.</para>
      /// </summary>
      UnknownError,
    }

    /// <summary>
    ///   <para>Specifies what audio sources should be recorded while recording the video.</para>
    /// </summary>
    public enum AudioState
    {
      /// <summary>
      ///   <para>Only include the mic audio in the video recording.</para>
      /// </summary>
      MicAudio,
      /// <summary>
      ///   <para>Only include the application audio in the video recording.</para>
      /// </summary>
      ApplicationAudio,
      /// <summary>
      ///   <para>Include both the application audio as well as the mic audio in the video recording.</para>
      /// </summary>
      ApplicationAndMicAudio,
      /// <summary>
      ///   <para>Do not include any audio in the video recording.</para>
      /// </summary>
      None,
    }

    /// <summary>
    ///   <para>A data container that contains the result information of a video recording operation.</para>
    /// </summary>
    public struct VideoCaptureResult
    {
      /// <summary>
      ///   <para>A generic result that indicates whether or not the VideoCapture operation succeeded.</para>
      /// </summary>
      public VideoCapture.CaptureResultType resultType;
      /// <summary>
      ///   <para>The specific Windows HRESULT code.</para>
      /// </summary>
      public long hResult;

      /// <summary>
      ///   <para>Indicates whether or not the operation was successful.</para>
      /// </summary>
      public bool success => this.resultType == VideoCapture.CaptureResultType.Success;
    }

    /// <summary>
    ///   <para>Called when a VideoCapture resource has been created.</para>
    /// </summary>
    /// <param name="captureObject">The VideoCapture instance.</param>
    public delegate void OnVideoCaptureResourceCreatedCallback(VideoCapture captureObject);

    /// <summary>
    ///   <para>Called when video mode has been started.</para>
    /// </summary>
    /// <param name="result">Indicates whether or not video mode was successfully activated.</param>
    public delegate void OnVideoModeStartedCallback(VideoCapture.VideoCaptureResult result);

    /// <summary>
    ///   <para>Called when video mode has been stopped.</para>
    /// </summary>
    /// <param name="result">Indicates whether or not video mode was successfully deactivated.</param>
    public delegate void OnVideoModeStoppedCallback(VideoCapture.VideoCaptureResult result);

    /// <summary>
    ///   <para>Called when the web camera begins recording the video.</para>
    /// </summary>
    /// <param name="result">Indicates whether or not video recording started successfully.</param>
    public delegate void OnStartedRecordingVideoCallback(VideoCapture.VideoCaptureResult result);

    /// <summary>
    ///   <para>Called when the video recording has been saved to the file system.</para>
    /// </summary>
    /// <param name="result">Indicates whether or not video recording was saved successfully to the file system.</param>
    public delegate void OnStoppedRecordingVideoCallback(VideoCapture.VideoCaptureResult result);
  }
}
